<template>
  <el-card shadow="never">
    <!-- 头部 -->
    <div slot="header">
      <el-breadcrumb separator='>'>
        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item>角色管理</el-breadcrumb-item>
        <el-breadcrumb-item>角色列表</el-breadcrumb-item>
      </el-breadcrumb>
    </div>

    <!-- 主体内容 -->
    <el-alert title="注意:只允许为第三级分类设置相关参数"
              type="warning">
    </el-alert>
    <br>
    <!-- 级联控件 -->
    <p>请选择分类: <el-cascader v-model="cateList"
                   :options="allCateList"
                   @change="changeCate"
                   clearable
                   :props="{
                           label:'cat_name',
                           value:'cat_id',
                           children:'children',
                       }"></el-cascader>
    </p>

    <!-- tab组件   @tab-click tap栏切换时触发的事件，切换tap栏时，触发 changeCate，通过判断，发送请求-->
    <el-tabs v-model="activeName"
             @tab-click="changeCate">
      <el-tab-pane label="动态参数"
                   name="many">
        <!-- 动态参数的内容 -->
        <el-button type="primary"
                   :disabled="btnDisabled"
                   @click="isAddShow = true">添加动态参数</el-button>
        <br><br>
        {{manyList}}
        <!-- 动态参数表格 -->
        <el-table :data="manyList"
                  border>
          <el-table-column type="expand"
                           width="120">

            <!-- 折叠列渲染参数值  -->
            <!-- 标签 -->
            <template slot-scope="scope">
              <el-tag v-for="(item,index) in scope.row.attr_vals"
                      :key="index"
                      closable
                      @close="delAttrVal(scope.row,index)">{{item}}</el-tag>
              <!-- 增加的输入框 每一行都要有自己的inputVisible和inputValue 也就是每一行都要有自己的输入框和开启输入框的状态控制属性-->
              <!-- 所以 要提前给每行数据增加属于自己的输入框内容 inputValue 和 inputVisible 输入框开关-->
              <!-- v-if 控制输入框是否显示 -->
              <!-- v-model 绑定输入框的值 -->
              <!-- @keyup键盘抬起事件，绑定了enter回车    @blur失去焦点事件 -->
              <el-input class="input-new-tag"
                        v-if="scope.row.inputVisible"
                        v-model="scope.row.inputValue"
                        ref="saveTagInput"
                        @keyup.enter.native="handleInputConfirm(scope.row)"
                        @blur="handleInputConfirm(scope.row)"
                        size="small">
              </el-input>
              <!-- 增加按钮 -->
              <el-button v-else
                         class="button-new-tag"
                         size="small"
                         @click="showInput(scope.row)">+ New Tag</el-button>

            </template>
          </el-table-column>
          <el-table-column type="index"
                           label="序号"
                           width="160"></el-table-column>
          <el-table-column prop="attr_name"
                           label="参数名"></el-table-column>
          <el-table-column label="操作">
            <!-- 操作列 -->
            <template slot-scope="scope">
              <!-- 修改 -->
              <el-button size="small"
                         type="success"
                         icon="el-icon-edit"
                         circle></el-button>
              <!-- 删除 -->
              <el-button @click="delAttr(scope.row)"
                         size="small"
                         type="danger"
                         icon="el-icon-delete"
                         circle></el-button>
            </template>

          </el-table-column>
        </el-table>
      </el-tab-pane>
      <!-- ------------------------------------------------------------------------------------------- -->
      <el-tab-pane label="静态属性"
                   name="only">
        <!-- 静态属性的内容 -->
        <el-button type="primary"
                   :disabled="btnDisabled"
                   @click="isAddShow = true">添加静态属性</el-button>
        <br><br>
        {{onlyList}}
        <!-- 静态属性表格 -->
        <el-table :data="onlyList"
                  border>
          <el-table-column type="expand"
                           width="120">
            <!-- 折叠列渲染参数值  -->
          </el-table-column>
          <el-table-column type="index"
                           label="序号"
                           width="160"></el-table-column>
          <el-table-column prop="attr_name"
                           label="参数名"></el-table-column>
          <el-table-column label="操作">
            <!-- 操作列 -->
            <template slot-scope="scope">
              <!-- 修改 -->
              <el-button size="small"
                         type="success"
                         icon="el-icon-edit"
                         circle></el-button>
              <!-- 删除 -->
              <el-button @click="delAttr(scope.row)"
                         size="small"
                         type="danger"
                         icon="el-icon-delete"
                         circle></el-button>
            </template>

          </el-table-column>
        </el-table>
      </el-tab-pane>

    </el-tabs>

    <!-- 添加动态或静态参数 -->
    <el-dialog :title="this.activeName === 'many' ? '添加动态属性' : '添加静态参数'"
               :visible.sync="isAddShow"
               width="30%">
      <!-- 表单 -->
      <el-form :model="addFormInfo"
               ref="addFormInfo"
               :rules="addFormRules"
               label-width="100px"
               size="normal">
        <el-form-item label="参数名称"
                      prop="attr_name">
          <el-input v-model="addFormInfo.attr_name"></el-input>
        </el-form-item>
      </el-form>

      <span slot="footer">
        <el-button @click="isAddShow = false">取消</el-button>
        <el-button type="primary"
                   @click="addSubmit">确定</el-button>
      </span>
    </el-dialog>

  </el-card>
</template>

<script>
export default {
  name: 'Params',
  data() {
    return {
      cateList: [], //选择的分类信息
      allCateList: [], //所有分类数据
      activeName: 'many',
      manyList: [], //用来存储动态属性
      onlyList: [], //用来存储静态参数
      isAddShow: false, //添加参数弹框
      addFormInfo: {
        //用户输入的参数名
        attr_name: ''
      },
      //   参数校验
      addFormRules: {
        attr_name: [
          { required: true, message: '请输入参数名', trigger: 'blur' }
        ]
      },
      inputVisible: false, //用来控制下面的 添加标签 的输入框是否显示
      inputValue: '' //下面的标签输入框的值
    }
  },
  created() {
    this.getAllCateList()
  },
  //   计算属性
  computed: {
    //   用来控制按钮是否启用
    btnDisabled() {
      return this.cateList.length === 0
    },
    // 分类 id
    cateId() {
      if (this.cateList.length === 3) {
        return this.cateList[2]
      } else {
        return ''
      }
    }
  },
  methods: {
    // 请求分类选项列表
    async getAllCateList() {
      const { data: res } = await this.$axios.get('/categories')
      //   失败
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      //   成功
      this.allCateList = res.data
    },
    // 当级联发生变化时触发
    async changeCate() {
      // val 是级联选择器的值
      // 如果不是三级就跳出
      if (this.cateList.length !== 3) {
        //就把数组清空,不能让数组有值
        this.cateList = []
        this.manyList = []
        this.onlyList = []
        return false
      }
      //   是三级就获取对应三级的静态参数和动态属性
      let { data: res } = await this.$axios.get(
        '/categories/' + this.cateId + '/attributes',
        {
          params: { sel: this.activeName }
        }
      )
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)

      //   赋值，因为值有动态属性和静态参数两种，我们准备了两个容器来存储，到底赋值给谁
      //   因为 tap 标签组件的  v-model="" 的值 actuveName 决定了当前显示哪个标签，所以通过这个值
      //   可以得知现在选中是是动态属性还是静态参数，然后通过 actuveName 拼接 List的方式来决定赋值给
      //   manyList 还是 onlyList (注意这两个名称是自己取的存放不同数据的变量)
      //  1.获取到数据之后处理数据中的 attr_vals字段，将其变成数组
      //  2.每行数据增加属于自己的输入框内容 inputValue 和 inputVisible 输入框开关
      //    增加的输入框 每一行都要有自己的inputVisible和inputValue 也就是每一行都要有自己的输入框和开启输入框的状态控制属性
      const list = res.data.map(val => {
        val.attr_vals = val.attr_vals ? val.attr_vals.split(',') : []
        val.inputVisible = false
        val.inputValue = ''
        return val
      })
      this[this.activeName + 'List'] = list
    },
    // 添加参数
    addSubmit() {
      this.$refs.addFormInfo.validate(async valid => {
        if (!valid) return
        const { data: res } = await this.$axios.post(
          `categories/${this.cateId}/attributes`,
          {
            attr_name: this.addFormInfo.attr_name,
            attr_sel: this.activeName
          }
        )
        //   失败
        if (res.meta.status !== 201) return this.$message.error(res.meta.msg)
        //   成功
        this.$message.success(res.meta.msg)
        // 清空表单
        this.$refs.addFormInfo.resetFields()
        this.isAddShow = false
        //   拉取数据
        this.changeCate()
      })
    },
    // 删除参数
    async delAttr(val) {
      try {
        // 确认删除弹框组件
        await this.$confirm(`确认删除吗？`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })

        // 发送请求
        const { data: res } = await this.$axios.delete(
          `/categories/${val.cat_id}/attributes/${val.attr_id}`
        )
        // 失败
        if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
        // 成功
        this.$message.success(res.meta.msg)
        // 成功
        // 重新渲染
        this.changeCate()
      } catch (error) {
        //   console.log(error);//这里拦截了错误，如果出现错误，打开这个可以查看错误信息
        this.$message.info('取消删除')
      }
    },
    // 打开添加参数值输入框
    showInput(row) {
      //row表示当前行的数据
      row.inputVisible = true
      //    this.$nextTick  等到 DOM 渲染完成之后再做某个事情
      this.$nextTick(() => {
        //    等到 DOM 渲染完成之后再去聚焦输入框，因为输入框是通过 v-if 创建的，
        //    因为，inputVisible = true 打开输入框，之后，v-if会去创建这个输入框，创建的过程是需要时间的，这个时候直接聚焦是找不到 DOM 的
        //    所以聚焦要等 DOM 渲染完成，输入框出现之后，再去执行
        this.$refs.saveTagInput.$refs.input.focus()
      })
    },
    async handleInputConfirm(row) {
      // 回车或者失去焦点时执行此函数
      // 1.判断
      if (!row.inputValue) {
        //回车或者失焦时如果没有输入值
        row.inputVisible = false //关闭输入框
        return false //退出
      }
      // 2.将当前输入框的值添加到当前行的 attr_vals
      row.attr_vals.push(row.inputValue)
      // 3.发送请求
      const attr_vals = row.attr_vals.join(',') //后台要求接收 attr_vals 字段，但是这个字段之前已经被转成了数组，所以现在要把数组转回字符串
      const { data: res } = await this.$axios.put(
        `categories/${row.cat_id}/attributes/${row.attr_id}`,
        {
          attr_name: row.attr_name,
          attr_sel: row.attr_sel,
          attr_vals //提交所有参数的字符串
        }
      )
      //   失败
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      // 成功
      this.$message.success(res.meta.msg)
      // 清空输入框的值
      row.inputValue = ''
      // 关闭输入框
      row.inputVisible = false
    },
    async delAttrVal(row, dex) {
      try {
        await this.$confirm(`确认删除吗？`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        let attr_vals = [...row.attr_vals]
        attr_vals.splice(idx, 1)
        attr_vals = attr_vals.join(',')
        const { data: res } = await this.$axios.put(
          `categories/${row.cat_id}/attributes/${row.attr_id}`,
          {
            attr_name: row.attr_name,
            attr_sel: row.attr_sel,
            attr_vals //提交所有参数的字符串
          }
        )
        if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
        this.$message.success(res.meta.msg)
        row.attr_vals.splice(idx, 1)
      } catch (error) {
        this.$message.info('取消删除')
      }
    }
  }
}
</script>

<style scope>
.el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 150px !important;
  margin-left: 10px;
  vertical-align: bottom;
}
</style>